#include "syntax_parser.h"
#include "errors_warnings.h"

#include "main_container.h"
extern MainContainer * CompilerData;

// <if_block> ~ if ( <expression> ) { <model_structure> } <else_structure>  {if}
void Parser::Parse_IfBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_IfBlock");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {if}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIf )
	{
		// write type of production in this node
		parent->Production = Gr_IfBlock__if_spLPar_Expression_spRPar_spLCBrac_ModelStructure_spRCBrac_ElseStructure;

		// process terminal symbol 'if' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		// if current lexic unit is in the select set of {(}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis )
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Expression(newNode2);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		// if current lexic unit is in the select set of {)}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis )
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		// if current lexic unit is in the select set of {{}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace )
		{
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			newNode4->LexUnitID=this->CurrentLexicPosition;
			newNode4->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <model_structure> 
		SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode5);
		Parse_ModelStructure(newNode5);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		// if current lexic unit is in the select set of {}}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace )
		{
			SyntaxTreeNode * newNode6 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode6);
			newNode6->LexUnitID=this->CurrentLexicPosition;
			newNode6->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <else_structure> 
		SyntaxTreeNode * newNode7 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode7);
		Parse_ElseStructure(newNode7);

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_IF_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_IfBlock");
#endif
}


// <wait_block> ~ wait <on_sensitivity_list> <forming_expression>  <while_until> ( <expression> ) <then_structure> <else_structure> <timeout> ;  {wait}
void Parser::Parse_WaitBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_WaitBlock");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {wait}
	if( currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWait )
	{
		// write type of production in this node
		parent->Production = Gr_WaitBlock__wait_OnSensitivityList_FormingExpression_WhileUntil_spLPar_Expression_spRPar_ThenStructure_ElseStructure_Timeout_spSemiCol;

		// process terminal symbol 'wait' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <on_sensitivity_list> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_OnSensitivityList(newNode2);

		// process nonterminal symbol <forming_expression> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_FormingExpression(newNode1);

		// process nonterminal symbol <while_until> 
		SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode3);
		Parse_WhileUntil(newNode3);

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		// if current lexic unit is in the select set of {(}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis )
		{
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			newNode4->LexUnitID=this->CurrentLexicPosition;
			newNode4->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode5);
		Parse_Expression(newNode5);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		// if current lexic unit is in the select set of
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis )
		{
			SyntaxTreeNode * newNode6 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode6);
			newNode6->LexUnitID=this->CurrentLexicPosition;
			newNode6->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <then_structure> 
		SyntaxTreeNode * newNode7 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode7);
		Parse_ThenStructure(newNode7);

		// process nonterminal symbol <else_structure> 
		SyntaxTreeNode * newNode8 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode8);
		Parse_ElseStructure(newNode8);

		// process nonterminal symbol <timeout> 
		SyntaxTreeNode * newNode9 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode9);
		Parse_Timeout(newNode9);

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {;}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			SyntaxTreeNode * newNode10 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode10);
			newNode10->LexUnitID=this->CurrentLexicPosition;
			newNode10->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_WAIT_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_WaitBlock");
#endif
}


// <on_sensitivity_list> ~ on <sensitivity_list>  {on}
// <on_sensitivity_list> ~ ? {forming, while, until}
void Parser::Parse_OnSensitivityList(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_OnSensitivityList");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif	
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {on}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOn )
	{
		// write type of production in this node
		parent->Production = Gr_OnSensitivityList__on_SensitivityList;

		// process terminal symbol 'on' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <sensitivity_list> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_SensitivityList(newNode1);

	}

	//if current lexic unit is in the select set of {forming, while,until}
	else if(currentUnit.type == LUTypeKeyword && 
		(currentUnit.subtype == KeywordWhile || currentUnit.subtype== KeywordUntil|| currentUnit.subtype== KeywordForming))
	{
		// write type of production in this node
		parent->Production = Gr_OnSensitivityList__epsilon;

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_ON_SENSITIVITY_LIST_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_OnSensitivityList");
#endif
}



// <while_until> ~ while  {while}
// <while_until> ~ until  {until}
void Parser::Parse_WhileUntil(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_WhileUntil");
#endif
	
	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif	
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {while}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWhile )
	{
		// write type of production in this node
		parent->Production = Gr_WhileUntil__while;

		// process terminal symbol 'while' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}

	//if current lexic unit is in the select set of {until}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUntil )
	{
		// write type of production in this node
		parent->Production = Gr_WhileUntil__until;

		// process terminal symbol 'until' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_WHILE_UNTIL_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_WhileUntil");
#endif
}


// <then_structure> ~ then { <model_structure> }  {then}
// <then_structure> ~ ? {else, timeout, ;}
void Parser::Parse_ThenStructure(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ThenStructure");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {then}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordThen )
	{
		// write type of production in this node
		parent->Production = Gr_ThenStructure__then_spLCBrac_ModelStructure_spRCBrac;

		// process terminal symbol 'then' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {{}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace )
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <model_structure> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_ModelStructure(newNode2);


		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {}}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}

	//if current lexic unit is in the select set of {else, timeout, ;}
	else if(
		//keywords
		(currentUnit.type == LUTypeKeyword && 
		(currentUnit.subtype == KeywordElse || currentUnit.subtype == KeywordTimeout)) ||
		//;
		(currentUnit.type == LUTypeSpecialCharacter && 
		currentUnit.subtype == SpecialCharacterSemicolon)
		)

	{
		// write type of production in this node
		parent->Production = Gr_ThenStructure__epsilon;

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_THEN_STRUCTURE_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ThenStructure");
#endif
}


// <else_structure> ~ else { <model_structure> }  {else}
// <else_structure> ~ ? {timeout, ;, NAME, generate, terminate, advance, enter, leave, seize, release, inqueue, outqueue, arrive, depart, model, goto, if, wait, join, create, split, gather, execute, exec, }}
void Parser::Parse_ElseStructure(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ElseStructure");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {else}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordElse )
	{
		// write type of production in this node
		parent->Production = Gr_ElseStructure__else_spLCBrac_ModelStructure_spRCBrac;

		// process terminal symbol 'else' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {{}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace )
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <model_structure> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_ModelStructure(newNode2);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {}}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace )
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}

	//if current lexic unit is in the select set of {timeout, ;, NAME, generate, terminate, advance,
	//enter, leave, seize, release, inqueue, outqueue, arrive, depart, model, goto, if, wait, join, 
	//create, split, gather, execute, exec, }}
	else if(
		//Keywords
		(currentUnit.type == LUTypeKeyword &&
		(currentUnit.subtype == KeywordTimeout ||
		currentUnit.subtype == KeywordGenerate ||
		currentUnit.subtype == KeywordTerminate ||
		currentUnit.subtype == KeywordAdvance ||
		currentUnit.subtype == KeywordEnter ||
		currentUnit.subtype == KeywordLeave ||
		currentUnit.subtype == KeywordSeize ||
		currentUnit.subtype == KeywordRelease ||
		currentUnit.subtype == KeywordInqueue ||
		currentUnit.subtype == KeywordOutqueue ||
		currentUnit.subtype == KeywordArrive ||
		currentUnit.subtype == KeywordDepart ||
		currentUnit.subtype == KeywordModel ||
		currentUnit.subtype == KeywordGoto ||
		currentUnit.subtype == KeywordIf ||
		currentUnit.subtype == KeywordWait ||
		currentUnit.subtype == KeywordJoin ||
		currentUnit.subtype == KeywordCreate ||
		currentUnit.subtype == KeywordSplit ||
		currentUnit.subtype == KeywordGather ||
		currentUnit.subtype == KeywordExecute ||
		currentUnit.subtype == KeywordExec))  ||
		//;, }
		(currentUnit.type == LUTypeSpecialCharacter && 
		(currentUnit.subtype == SpecialCharacterSemicolon ||
		currentUnit.subtype == SpecialCharacterRightCurlyBrace)) ||
		//NAME
		(currentUnit.type == LUTypeIdentifier)


		)
	{
		// write type of production in this node
		parent->Production = Gr_ElseStructure__epsilon;

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_ELSE_STRUCTURE_BEGINING);

		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ElseStructure");
#endif
}




// <sensitivity_list> ~ <name> <sensitivity_list_adds>  {NAME}
void Parser::Parse_SensitivityList(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SensitivityList");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {NAME}
	if(	currentUnit.type == LUTypeIdentifier ) 
	{
		// write type of production in this node
		parent->Production = Gr_SensitivityList__Name_SensitivityListAdds;

		// process nonterminal symbol <name> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_Name(newNode0);

		// process nonterminal symbol <sensitivity_list_adds> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_SensitivityListAdds(newNode1);

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SENSITIVITY_LIST_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SensitivityList");
#endif
}



// TIP 1
// <sensitivity_list_adds> ~ <sensitivity_list_add> <sensitivity_list_adds>  {,}
// <sensitivity_list_adds> ~ ? {forming, while, until}
void Parser::Parse_SensitivityListAdds(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SensitivityListAdds");
#endif

	LexicUnit currentUnit;
	
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif	
	
	

	do{
		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		//if current lexic unit is in the select set of {,}
		if(
			//currentUnit == ,
			currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterComma
			)
		{
			// write type of production in this node
			parent->Production = Gr_SensitivityListAdds__SensitivityListAdd_SensitivityListAdds;

			// process nonterminal symbol <sensitivity_list_add> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_SensitivityListAdd(newNode0);
			
		}

		//if current lexic unit is in the select set of {forming, while, until}
		else if(currentUnit.type == LUTypeKeyword &&
			(currentUnit.subtype == KeywordWhile ||	currentUnit.subtype == KeywordUntil  ||	currentUnit.subtype == KeywordForming))
		{
			// write type of production in this node
			parent->Production = Gr_SensitivityListAdds__SensitivityListAdd_SensitivityListAdds;
			break;

		}


		else
		{
			// ERROR has been found
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SENSITIVITY_LIST_ADDS_BEGINING);
			// MAKE LOGICAL RECOVERING
			this->CurrentLexicPosition++;
			break;
		}
	}while (1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SensitivityListAdds");
#endif
}


// <sensitivity_list_add> ~ , <name>  {,}
void Parser::Parse_SensitivityListAdd(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SensitivityListAdd");
#endif
	LexicUnit currentUnit;
	
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {,}
	if(	currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterComma )
	{
		// write type of production in this node
		parent->Production = Gr_SensitivityListAdd__spComma_Name;

		// process terminal symbol ',' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <name> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_Name(newNode1);

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SENSITIVITY_LIST_ADD_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SensitivityListAdd");
#endif
}


// <join_group_block> ~ join group <expression> ;  {join}
void Parser::Parse_JoinGroupBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_JoinGroupBlock");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {join}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordJoin	)
	{
		// write type of production in this node
		parent->Production = Gr_JoinGroupBlock__join_group_Expression_spSemiCol;

		// process terminal symbol 'join' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol 'group' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {group}
		if ( currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGroupLower )
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_GROUP_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Expression(newNode2);

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {;}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon )
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_JOIN_GROUP_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_JoinGroupBlock");
#endif
}



// <leave_group_block> ~ leave group <expression> ;  {leave}
void Parser::Parse_LeaveGroupBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_LeaveGroupBlock");
#endif

	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {leave}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordLeave )
	{
		// write type of production in this node
		parent->Production = Gr_LeaveGroupBlock__leave_group_Expression_spSemiCol;

		// process terminal symbol 'leave' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol 'group' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of  {group}
		if ( currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGroupLower )
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_GROUP_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Expression(newNode2);

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {;}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon )
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEAVE_GROUP_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_LeaveGroupBlock");
#endif
}


// <create_block> ~ create <upto_expression> <generate_transactions> <after_expression> <every_expression> <send_to> ;  {create}
void Parser::Parse_CreateBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_CreateBlock");
#endif
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif

	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {create}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordCreate )
	{
		// write type of production in this node
		parent->Production = Gr_CreateBlock__create_UptoExpression_GenerateTransactions_AfterExpression_EveryExpression_SendTo_spSemiCol;

		// process terminal symbol 'create' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <upto_expression> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_UptoExpression(newNode1);

		// process nonterminal symbol <generate_transactions> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_GenerateTransactions(newNode2);

		// process nonterminal symbol <after_expression> 
		SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode3);
		Parse_AfterExpression(newNode3);

		// process nonterminal symbol <every_expression> 
		SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode4);
		Parse_EveryExpression(newNode4);

		// process nonterminal symbol <send_to> 
		SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode5);
		Parse_SendTo(newNode5);

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {;}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon )
		{
			SyntaxTreeNode * newNode6 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode6);
			newNode6->LexUnitID=this->CurrentLexicPosition;
			newNode6->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_CREATE_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_CreateBlock");
#endif
}


// <send_to> ~ send to <name>  {send}
// <send_to> ~ ? {;}
void Parser::Parse_SendTo(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SendTo");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {send}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSend	)
	{
		// write type of production in this node
		parent->Production = Gr_SendTo__send_to_Name;

		// process terminal symbol 'send' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol 'to' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {to}
		if ( currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTo )

		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error  ERR_SYN_NO_TO_MATCH
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_TO_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <name> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Name(newNode2);

	}

	//if current lexic unit is in the select set of {;}
	else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon )
	{
		// write type of production in this node
		parent->Production = Gr_SendTo__epsilon;

	}


	else
	{
		// ERROR has been found		
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEND_TO_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SendTo");
#endif
}



// <split_block> ~ split <into_expression> <send_to> ;  {split}
void Parser::Parse_SplitBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SplitBlock");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {split}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSplit )
	{
		// write type of production in this node
		parent->Production = Gr_SplitBlock__split_IntoExpression_SendTo_spSemiCol;

		// process terminal symbol 'split' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <into_expression> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_IntoExpression(newNode1);

		// process nonterminal symbol <send_to> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_SendTo(newNode2);

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		//if current lexic unit is in the select set of {;}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon )
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SPLIT_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SplitBlock");
#endif
}
